package com.yantong.controller.assets;

import com.yantong.annotation.Log;
import com.yantong.constant.BalanceLogStyle;
import com.yantong.constant.BusinessCode;
import com.yantong.controller.BaseController;
import com.yantong.result.ResultVo;
import com.yantong.utils.DateUtils;
import com.yantong.utils.PageUtils;
import com.yantong.utils.excel.ExcelHelper;
import com.yantong.pojo.Balance;
import com.yantong.pojo.vo.BalanceExcelVo;
import com.yantong.pojo.BalanceLog;
import com.yantong.service.BalanceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

import static com.yantong.constant.RechargeType.BEHIND_DEDUCT;
import static com.yantong.constant.RechargeType.BEHIND_RECHARGE;

/**
 * 余额
 * @author kanghaixin
 * @date 2018/9/16.9:01
 */
@Controller
@RequestMapping("/finance/balance")
public class BalanceController extends BaseController {
    private static final String prefix = "finance/balance";
    @Autowired
    private BalanceService balanceService;

    private static final Logger logger = LoggerFactory.getLogger(BalanceController.class);
    /**
     * 余额列表页面
     * @return
     */
    @GetMapping()
    @RequiresPermissions("finance:balance:balance")
    public String balances(Model model) {
        model.addAllAttributes(getCentreIdModelInfo());
        return prefix + "/balances";
    }

    /**
     * 余额列表页面
     * @param role
     * @param start
     * @param end
     * @param queryItem
     * @param centreId
     * @param offset
     * @param limit
     * @return
     */
    @ResponseBody
    @GetMapping("/list")
    @RequiresPermissions("finance:balance:balance")
    public PageUtils<Balance> listBalances(Integer role,@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date start,@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date end, String queryItem, Long centreId,
                                           int offset, int limit) {
        Long teamId = getUserTeamId();
        return balanceService.listBalances(role, start, end,queryItem, centreId, teamId,offset, limit);
    }

    /**
     * 余额列表导出
     * @param role
     * @param start
     * @param end
     * @param queryItem
     * @param centreId
     */
    @RequiresPermissions("finance:balance:export")
    @GetMapping("/export")
    public void exportBalances(Integer role, Date start, Date end, String queryItem, Long centreId,
                               HttpServletResponse response) {
        List<List<Object>> resultData = new ArrayList<>();
        String[] head = {"用户ID", "昵称", "姓名", "手机号码", "等级","余额"};
        resultData.add(0, Arrays.asList(head));

        List<Balance> list = balanceService.listBalances(role,start, end,queryItem, centreId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (Balance balance: list) {
                if (balance == null) {
                    continue;
                }
                List<Object> row = new ArrayList<>();
                row.add(balance.getMid());
                row.add(balance.getNickname());
                row.add(balance.getRealname());
                row.add(balance.getMobile());
                if (balance.getIsteam() == 3) {
                    row.add("门店");
                }else if (balance.getIsSupplier() == 1) {
                    row.add("供应商");
                }else {
                    row.add("会员");
                }
                row.add(balance.getBalance());
                resultData.add(row);
            }
        }
        String fileName = "余额记录_" + DateUtils.format(new Date(), "yyyyMMddHHmmss");
        try {
            ExcelHelper.exportExcel(response, fileName, "余额记录", resultData);
        } catch (IOException e) {
            logger.info("export balance list error:{}", e.getMessage());
        }
    }

    /**
     * 余额总计
     * @param role
     * @param start
     * @param end
     * @param queryItem
     * @param centreId
     * @return
     */
    @ResponseBody
    @PostMapping("/getTotalBalance")
    @RequiresPermissions("finance:balance:balance")
    public ResultVo getTotalBalance(Integer role, @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date start,@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date end, String queryItem, Long centreId) {
        return ResultVo.ok().put("totalBalance", balanceService.getBalanceSum(role,start,end,queryItem,centreId));
    }

    /**
     * 充值页面
     * @param mid
     * @return
     */
    @RequiresPermissions("finance:balance:recharge")
    @GetMapping("/recharge/{mid}")
    public String recharge(@PathVariable Long mid, Model model) {
        model.addAttribute("balance", balanceService.getBalanceDetail(mid));
        return prefix +"/recharge";
    }

    /**
     * 后台充值
     * @param mid
     * @param money
     * @param remark
     * @return
     */
    @Log(module = "后台充值", operation = "后台用户充值")
    @ResponseBody
    @RequiresPermissions("finance:balance:recharge")
    @PostMapping("/rechargeSave")
    public ResultVo rechargeSave(Long mid, Double money, String remark) {
        if (mid == null || money == null) {
            return ResultVo.error();
        }
        if (balanceService.balanceRecharge(mid, money, BalanceLogStyle.RECHARGE.getCode(),BEHIND_RECHARGE.getType(),remark)< 1) {
            return ResultVo.error();
        }
        return ResultVo.ok();
    }

    /**
     * 扣款页面
     * @param mid
     * @param model
     * @return
     */
    @GetMapping("/deduct/{mid}")
    @RequiresPermissions("finance:balance:deduct")
    public String deduct(@PathVariable Long mid, Model model) {
        model.addAttribute("balance", balanceService.getBalanceDetail(mid));
        return prefix + "/deduct";
    }

    /**
     * 扣款保存
     * @param mid
     * @param money
     * @param remark
     * @return
     */
    @Log(module = "余额管理", operation = "保存扣款")
    @ResponseBody
    @PostMapping("/deductSave")
    @RequiresPermissions("finance:balance:deduct")
    public ResultVo deductSave(Long mid, Double money, String remark) {
        if (mid == null || money == null) {
            return ResultVo.error();
        }
        if (balanceService.balanceDeduct(mid, money, BalanceLogStyle.DEDUCT.getCode(),
                BEHIND_DEDUCT.getType(),remark)< 1) {
            return ResultVo.error();
        }
        return ResultVo.ok();
    }


    /**
     * 提现页面
     * @param mid
     * @param model
     * @return
     */
    @GetMapping("/cash/{mid}")
    @RequiresPermissions("finance:balance:cash")
    public String cash(@PathVariable Long mid, Model model) {
        model.addAttribute("balance", balanceService.getBalanceDetail(mid));
        return prefix + "/cash";
    }

    /**
     * 提现保存
     * @param mid
     * @param money
     * @param remark
     * @return
     */
    @Log(module = "余额管理", operation = "保存提现")
    @ResponseBody
    @PostMapping("/cashSave")
    @RequiresPermissions("finance:balance:cash")
    public ResultVo cashSave(Long mid, Double money, String remark) {
        if (mid == null || money == null) {
            return ResultVo.error();
        }
        if (balanceService.cash(mid, money, remark,null,null) <1){
            return ResultVo.error();
        }
        return ResultVo.ok();
    }

    /**
     * 收支明细
     * @param mid
     * @param model
     * @return
     */
    @RequiresPermissions("finance:balance:payin")
    @GetMapping("/payin/{mid}")
    public String payin(@PathVariable Long mid, Model model) {
        model.addAttribute("balanceLogStyles", BalanceLogStyle.getBalanceLogStyles());
        model.addAttribute("mid", mid);
        return prefix + "/payin";
    }

    /**
     * 会员余额流水
     * @param balanceLog
     * @param offset
     * @param limit
     * @return
     */
    @ResponseBody
    @GetMapping("/midBalanceLogs")
    @RequiresPermissions("finance:balance:payin")
    public PageUtils<BalanceLog> listBalanceLogs(BalanceLog balanceLog, int offset,int limit) {
        return balanceService.listBalanceLogs(balanceLog, offset, limit);
    }

//    /**
//     * 单会员余额明细
//     * @param balanceLog
//     * @param offset
//     * @param limit
//     * @return
//     */
//    @ResponseBody
//    @GetMapping("/midBalanceLogs")
//    @RequiresPermissions("finance:balance:payin")
//    public PageUtils<BalanceLog> listBalanceLogs(BalanceLog balanceLog, int offset,int limit) {
//        return balanceService.listBalanceLogs(balanceLog, offset, limit);
//    }

    /**
     * 批量充值
     * @param file
     * @return
     */
    @Log(module = "余额管理", operation = "批量充值")
    @ResponseBody
    @RequiresPermissions("finance:balance:excelRecharge")
    @PostMapping("/batchRecharge")
    public ResultVo batchRecharge(@RequestParam(value = "excelFile") MultipartFile file) throws Exception {
        if (file == null || StringUtils.isEmpty(file.getOriginalFilename())) {
           return ResultVo.error(BusinessCode.FILE_IMPORT_ERROR);
        }
        HashSet<String> defaultAllowFileType =new HashSet<>();
        defaultAllowFileType.add(".xls");
        defaultAllowFileType.add(".xlsx");
        if (!file.getOriginalFilename().contains(".") || !defaultAllowFileType.contains(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")))) {
            return ResultVo.error(BusinessCode.FILE_FORMAT_ERROR);
        }
        List<BalanceExcelVo> list = readExcelFile(file);
        if (balanceService.batchRecharge(list) <1) {
            return ResultVo.error();
        }
        return ResultVo.ok();
    }

    private List<BalanceExcelVo> readExcelFile(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        String format = fileName.substring(fileName.lastIndexOf(".")+1);
        System.out.println("文件名:"+fileName+",大小:"+file.getSize()/1024+"kb,格式:"+format);

        Workbook workbook = null;
        InputStream inputStream = null;
		/** 读取第一个sheet */
		List<BalanceExcelVo> result = null;
		try {
			inputStream = file.getInputStream();
			//- excel 2003
			if("xls".equals(format)){
			    workbook = new HSSFWorkbook(inputStream);
			}else if ("xlsx".equals(format)){
			    workbook = new XSSFWorkbook(inputStream);
			}

			result = new ArrayList<>();
			int sheets = workbook.getNumberOfSheets();
			if(sheets > 0){
			    Sheet sheet = workbook.getSheetAt(0);
			    List<BalanceExcelVo> ind = readSheet(sheet);
			    result.addAll(ind);
			}
		} catch (IOException e) {

			e.printStackTrace();
		}finally {
 			try {
 				if (inputStream != null) {
 			        inputStream.close();
 				}
			} catch (Exception e) {

				e.printStackTrace();
			}
		}
        return result;
    }

    /**
     * 解析sheet.
     *     sheet前三列分别为对应到bean的字段、字段类型、excel表头
     *
     * @param sheet
     * @return
     */
    private List<BalanceExcelVo> readSheet(Sheet sheet) {
        List<BalanceExcelVo> result = new ArrayList<>();
        //- Excel行数
        int totalRows = sheet.getPhysicalNumberOfRows();
        for (int r = 1; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null){
                continue;
            }
            BalanceExcelVo map = new BalanceExcelVo();
            /** 循环Excel的列 */
            try {
                Cell cell = row.getCell(0);
                if (cell == null) {
                    continue;
                }
                cell.setCellType(CellType.STRING);
                if (StringUtils.isEmpty(cell.getStringCellValue())) {
                    continue;
                }
                map.setMid(Long.parseLong(cell.getStringCellValue()));

                Cell cell2 = row.getCell(1);
                cell2.setCellType(CellType.STRING);

                if (StringUtils.isEmpty(cell2.getStringCellValue())) {
                    continue;
                }
                map.setAmount(new BigDecimal(cell2.getStringCellValue()));

                Cell cell3 = row.getCell(2);
                cell3.setCellType(CellType.STRING);
                map.setTname(cell3.getStringCellValue());

                Cell cell4 = row.getCell(3);
                cell4.setCellType(CellType.STRING);
                map.setRemark(cell4.getStringCellValue());
            } catch (NumberFormatException e) {
                logger.error("readSheet error:{}", e.getMessage());
            }
            result.add(map);
        }
        return result;
    }
}

